/*
 * Created on 11-Jan-2005
 * Created by Paul Gardner
 * Copyright (C) Azureus Software, Inc, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

package com.aelitis.azureus.core.dht;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import com.aelitis.azureus.core.dht.control.DHTControl;
import com.aelitis.azureus.core.dht.db.DHTDB;
import com.aelitis.azureus.core.dht.nat.DHTNATPuncher;
import com.aelitis.azureus.core.dht.router.DHTRouter;
import com.aelitis.azureus.core.dht.transport.DHTTransport;
import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
import com.aelitis.azureus.core.dht.transport.DHTTransportValue;

/**
 * @author parg
 * 
 */

public interface DHT {
    // all property values are Integer values

    public static final String PR_CONTACTS_PER_NODE = "EntriesPerNode";
    public static final String PR_NODE_SPLIT_FACTOR = "NodeSplitFactor";
    public static final String PR_SEARCH_CONCURRENCY = "SearchConcurrency";
    public static final String PR_LOOKUP_CONCURRENCY = "LookupConcurrency";
    public static final String PR_MAX_REPLACEMENTS_PER_NODE = "ReplacementsPerNode";
    public static final String PR_CACHE_AT_CLOSEST_N = "CacheClosestN";
    public static final String PR_ORIGINAL_REPUBLISH_INTERVAL = "OriginalRepublishInterval";
    public static final String PR_CACHE_REPUBLISH_INTERVAL = "CacheRepublishInterval";
    public static final String PR_ENCODE_KEYS = "EncodeKeys";
    public static final String PR_ENABLE_RANDOM_LOOKUP = "EnableRandomLookup";

    public static final short FLAG_NONE = 0x0000;
    public static final short FLAG_SINGLE_VALUE = FLAG_NONE;
    public static final short FLAG_DOWNLOADING = 0x0001;
    public static final short FLAG_SEEDING = 0x0002;
    public static final short FLAG_MULTI_VALUE = 0x0004;
    public static final short FLAG_STATS = 0x0008;
    public static final short FLAG_ANON = 0x0010;
    public static final short FLAG_PRECIOUS = 0x0020;
    public static final short FLAG_PUT_AND_FORGET = 0x0040; // local only
    public static final short FLAG_OBFUSCATE_LOOKUP = 0x0080; // local only
    public static final short FLAG_LOOKUP_FOR_STORE = 0x0100; // local only
    public static final short FLAG_HIGH_PRIORITY = 0x0200; // local only, used in plugin to transmit priority through call stack

    public static final int MAX_VALUE_SIZE = 512;

    public static final byte REP_FACT_NONE = 0;
    public static final byte REP_FACT_DEFAULT = (byte) 0xff;

    // diversification types, don't change as serialised!!!!

    public static final byte DT_NONE = 1;
    public static final byte DT_FREQUENCY = 2;
    public static final byte DT_SIZE = 3;

    public static final String[] DT_STRINGS = { "", "None", "Freq", "Size" };

    public static final int NW_MAIN = 0;
    public static final int NW_CVS = 1;
    public static final int NW_MAIN_V6 = 3;

    public void put(byte[] key, String description, byte[] value, short flags, DHTOperationListener listener);

    /**
     * default is HIGH PRIORITY. if you change to low priority then do so consistently as operations can get out of order otherwise
     * 
     * @param key
     * @param description
     * @param value
     * @param flags
     * @param high_priority
     * @param listener
     */

    public void put(byte[] key, String description, byte[] value, short flags, boolean high_priority, DHTOperationListener listener);

    public void
            put(byte[] key, String description, byte[] value, short flags, byte life_hours, boolean high_priority, DHTOperationListener listener);

    public void put(byte[] key, String description, byte[] value, short flags, byte life_hours, byte replication_control, // 4 bits 1->14 republish
                                                                                                                          // hours; 0=vuze default | 4
                                                                                                                          // bits 0->15 maintain
                                                                                                                          // replicas; [ff=no
                                                                                                                          // replication control-use
                                                                                                                          // default]
            boolean high_priority, DHTOperationListener listener);

    /**
     * Returns value if originated from here for key
     * 
     * @param key
     * @return
     */

    public DHTTransportValue getLocalValue(byte[] key);

    /**
     * @param key
     * @param max_values
     * @param timeout
     * @param listener
     */

    public void get(byte[] key, String description, short flags, int max_values, long timeout, boolean exhaustive, boolean high_priority,
            DHTOperationListener listener);

    public byte[] remove(byte[] key, String description, DHTOperationListener listener);

    public byte[] remove(DHTTransportContact[] contacts, byte[] key, String description, DHTOperationListener listener);

    public boolean isDiversified(byte[] key);

    public int getIntProperty(String name);

    public DHTTransport getTransport();

    public DHTRouter getRouter();

    public DHTControl getControl();

    public DHTDB getDataBase();

    public DHTNATPuncher getNATPuncher();

    public DHTStorageAdapter getStorageAdapter();

    /**
     * externalises information that allows the DHT to be recreated at a later date and populated via the import method
     * 
     * @param os
     * @param max
     *            maximum to export, 0 -> all
     * @throws IOException
     */

    public void exportState(DataOutputStream os, int max)

    throws IOException;

    /**
     * populate the DHT with previously exported state
     * 
     * @param is
     * @throws IOException
     */

    public void importState(DataInputStream is)

    throws IOException;

    /**
     * Integrate the node into the DHT Can be invoked more than once if additional state is imported
     */

    public void integrate(boolean full_wait);

    public void setSuspended(boolean susp);

    public void destroy();

    public boolean isSleeping();

    public void setLogging(boolean on);

    public DHTLogger getLogger();

    public void print(boolean full);

    public void addListener(DHTListener listener);

    public void removeListener(DHTListener listener);
}
